<?php declare(strict_types=1);
/**
 * @author      xianganyall <xianganyall@gmail.com>
 * @copyright   2023-2025 owner
 **/

namespace Srv\Libs\Common;

use Srv\Libs\Frame\EnvData;
use Srv\Libs\Frame\ResponseData;
use Srv\Libs\Tools\Http;

final class CommFrom
{
    /**
     * @param string $name
     * @param string $order
     * @param bool $isFilter
     * @param bool $isSet
     * @return string
     * 获取字符串值(SERVER-COOKIE-POST-GET)
     */
    public static function getStringOrder(string $name, string $order = 'SCPG', bool $isFilter = false, bool &$isSet = false):string
    {
        $value          = '';
        $orderLength    = strlen(CommString::trimAll($order));
        if($orderLength < 1) return $value;
        foreach(str_split($order) as $type){
            switch(strtoupper($type)){
                case 'S':{
                    $value = trim(strval(self::getServer($name, $isFilter, $isSet)));
                    break;
                }
                case 'C':{
                    $value = trim(strval(self::getCookie($name, $isFilter, $isSet)));
                    break;
                }
                case 'P':{
                    $value = trim(strval(self::getPost($name, $isFilter, $isSet)));
                    break;
                }
                case 'G':{
                    $value = trim(strval(self::getGet($name, $isFilter, $isSet)));
                    break;
                }
            }
            if(strlen($value) > 0) break;
        }
        return $value;
    }

    /**
     * @param string $name
     * @param bool $isFilter
     * @param bool $isSet
     * @return string
     * 获取字符串值(POST-GET)
     */
    public static function getString(string $name, bool $isFilter = false, bool &$isSet = false):string
    {
        $value      = trim(strval(self::getPost($name, $isFilter, $isSet)));
        CommString::isEmpty($value) && $value = trim(strval(self::getGet($name, $isFilter, $isSet)));
        return $value;
    }

    /**
     * @param string $name
     * @param bool $isFilter
     * @param bool $isSet
     * @return int
     * 获取数字值(POST-GET)
     */
    public static function getInt(string $name, bool $isFilter = false, bool &$isSet = false):int
    {
        return intval(self::getString($name, $isFilter, $isSet));
    }

    /**
     * @param string $name
     * @param bool $isFilter
     * @param bool $isSet
     * @return float
     * 获取浮点数(POST-GET)
     */
    public static function getFloat(string $name, bool $isFilter = false, bool &$isSet = false):float
    {
        return floatval(self::getString($name, $isFilter, $isSet));
    }

    /**
     * @param string $name
     * @param bool $isFilter
     * @param bool $isSet
     * @return bool
     * 获取Bool数(POST-GET)
     */
    public static function getBool(string $name, bool $isFilter = false, bool &$isSet = false):bool
    {
        $strBool        = trim(self::getString($name, $isFilter, $isSet));
        return CommString::getBoolByString($strBool);
    }

    /**
     * @param string $name
     * @param bool $isFilter
     * @param bool $isSet
     * @return array
     * 获取数组值(POST-GET)
     */
    public static function getArray(string $name, bool $isFilter = false, bool &$isSet = false):array
    {
        $value = self::getPost($name, $isFilter, $isSet);
        !is_array($value) && $value = self::getGet($name, $isFilter, $isSet);
        return is_array($value) ? $value : [];
    }

    /**
     * @param string $name
     * @param bool $isFilter
     * @param bool $isSet
     * @return array
     * 获取数组JSON值(POST-GET)
     */
    public static function getArrayByJson(string $name, bool $isFilter = false, bool &$isSet = false):array
    {
        $value = trim(self::getString($name, $isFilter, $isSet));
        return CommJson::decodeArray($value);
    }

    /**
     * @param string $name
     * @param bool $isFilter
     * @param bool $isSet
     * @return array|mixed|null|string
     * 获取HTTP-header值
     */
    public static function getServer(string $name, bool $isFilter = false, bool &$isSet = false)
    {
        if(!EnvData::isDataByServerItem($name)){
            $upperName = strtoupper($name);
            if($name !== $upperName) $name = Http::getHeaderName($upperName);
        }
        $value = EnvData::getDataByServerItem($name);
        $isSet = !($value === null);
        return $isFilter ? self::filterData($value) : $value;
    }

    /**
     * @param string $name
     * @param bool $isFilter
     * @param bool $isSet
     * @return array|mixed|null|string
     * 获取COOKIE值
     */
    public static function getCookie(string $name, bool $isFilter = false, bool &$isSet = false)
    {
        $value = EnvData::getDataByCookieItem($name);
        $isSet = !($value === null);
        return $isFilter ? self::filterData($value) : $value;
    }

    /**
     * @param string $name
     * @param bool $isFilter
     * @param bool $isSet
     * @return array|mixed|null|string
     * 获取POST值
     */
    public static function getPost(string $name, bool $isFilter = false, bool &$isSet = false)
    {
        $value = EnvData::getDataByPostItem($name);
        $isSet = !($value === null);
        return $isFilter ? self::filterData($value) : $value;
    }

    /**
     * @param string $name
     * @param bool $isFilter
     * @param bool $isSet
     * @return array|mixed|null|string
     * 获取GET值
     */
    public static function getGet(string $name, bool $isFilter = false, bool &$isSet = false)
    {
        $value = EnvData::getDataByGetItem($name);
        $isSet = !($value === null);
        return $isFilter ? self::filterData($value) : $value;
    }

    /**
     * @param string $name
     * @param $value
     * @return bool
     * 设置SERVER值
     */
    public static function setServer(string $name, $value):bool
    {
        EnvData::setDataToServerItem($name, $value);
        return true;
    }

    /**
     * @param string $name
     * @param $value
     * @return bool
     * 设置GET值
     */
    public static function setGet(string $name, $value):bool
    {
        EnvData::setDataToGetItem($name, $value);
        return true;
    }

    /**
     * @param string $name
     * @param $value
     * @return bool
     * 设置POST值
     */
    public static function setPost(string $name, $value):bool
    {
        EnvData::setDataToPostItem($name, $value);
        return true;
    }

    /**
     * @param string $name
     * @param string $value
     * @param array $cookieData
     * @return bool
     * 设置COOKIE值
     */
    public static function setCookie(string $name, string $value, array $cookieData = []):bool
    {
        EnvData::setDataToCookieItem($name, $value);
        ResponseData::addCustomCookie($name, $value, intval($cookieData['expires'] ?? 0), strval($cookieData['path'] ?? ''), strval($cookieData['domain'] ?? ''), !!($cookieData['secure'] ?? false), !!($cookieData['httponly'] ?? false));
        return true;
    }

    /**
     * @param string $value
     * @return string
     * 获取安全字符串
     */
    public static function filterString(string $value):string
    {
        if(strlen($value) < 3 || is_numeric($value)) return $value;
        if(preg_match("/^[a-z\d.\-_+ :;,|?\[\]{}=()*^%$#@!]+$/i", $value)) return $value;
        $value = preg_replace_callback("'<script[^>]*?>.*?</script>'si", static function(){return '';}, $value);
        $value = preg_replace_callback("'<[/!]*?[^<>]*?>'i", static function(){return '';}, $value);
        $value = preg_replace_callback("'([\r\n])\s+'", static function($match){return $match[1];}, $value);
        $value = preg_replace_callback("'&(quot|#34);'i", static function(){return '"';}, $value);
        $value = preg_replace_callback("'&(amp|#38);'i", static function(){return '&';}, $value);
        $value = preg_replace_callback("'&(lt|#60);'i", static function(){return '<';}, $value);
        $value = preg_replace_callback("'&(gt|#62);'i", static function(){return '>';}, $value);
        $value = preg_replace_callback("'&(nbsp|#160);'i", static function(){return ' ';}, $value);
        $value = preg_replace_callback("'&(iexcl|#161);'i", static function(){return chr(161);}, $value);
        $value = preg_replace_callback("'&(cent|#162);'i", static function(){return chr(162);}, $value);
        $value = preg_replace_callback("'&(pound|#163);'i", static function(){return chr(163);}, $value);
        $value = preg_replace_callback("'&(copy|#169);'i", static function(){return chr(169);}, $value);
        return preg_replace_callback("'&#(\d+);'", static function($match){return chr($match[1]);}, $value);
    }

    /**
     * @param $value
     * @return array|string
     * 对数据递归安全处理
     */
    private static function filterData($value)
    {
        if(is_array($value)){
            array_walk_recursive($value, [__CLASS__, __METHOD__]);
            return $value;
        }else if(is_string($value)){
            return self::filterString($value);
        }else{
            return $value;
        }
    }
}